<template>
  <div
      ref="editorRef" class="editor" contentEditable="true" v-html="editorText"
      @click="handleClick"
      @input="handleInput"
      @focus="handleFocus"
      @blur="handleBlur"
      style="user-select:text;-webkit-user-select:text;">
  </div>
</template>

<script>
import { onMounted, ref, reactive, toRefs, watch } from 'vue'

export default {
  props: {
    modelValue: { type: String, default: '' }
  },

  setup (props, { emit }) {
    const editorRef = ref(null)
    const data = reactive({
      editorText: props.modelValue,
      isChange: true,
      // 记录光标最后位置
      lastCursor: null
    })

    watch(() => props.modelValue, () => {
      if (data.isChange) {
        data.editorText = props.modelValue
      }
    })

    onMounted(() => {
      // 处理粘贴事件
      editorRef.value.addEventListener('paste', function (e) {
        // ...
      })
    })

    const handleInput = () => {
      emit('update:modelValue', editorRef.value.innerHTML)

      data.lastCursor = getLastCursor()
    }
    // 删除内容
    const handleDel = () => {
      let range
      let sel = window.getSelection()
      if (data.lastCursor) {
        sel.removeAllRanges()
        sel.addRange(data.lastCursor)
      }
      range = getLastCursor()
      range.collapse(false)
      document.execCommand('delete')
    }
    // 清空编辑器
    const handleClear = () => {
      editorRef.value.innerHTML = ''
      editorRef.value.focus()
    }

    // 点击编辑器
    const handleClick = () => {
      emit('clickFn')
      data.lastCursor = getLastCursor()
    }

    // 获取焦点
    const handleFocus = () => {
      data.isChange = false
      emit('focusFn')
      data.lastCursor = getLastCursor()
    }

    // 失去焦点
    const handleBlur = () => {
      data.isChange = true
      emit('blurFn')
    }

    // 获取光标最后位置
    const getLastCursor = () => {
      let sel = window.getSelection()
      if (sel && sel.rangeCount > 0) {
        return sel.getRangeAt(0)
      }
    }

    // 光标处插入内容 @param html 需要插入的内容
    const insertHtmlAtCursor = (html) => {
      // ...
    }

    return {
      ...toRefs(data),
      editorRef,

      handleInput,
      handleDel,
      handleClear,
      handleClick
      // ...
    }
  }
}
</script>
